Modernize and optimize pixel format operations across platforms.#2645
Conversation
| /// <param name="numBytes">The number of bytes to shift by.</param> | ||
| /// <returns>The <see cref="Vector128{Byte}"/>.</returns> | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public static Vector128<byte> ShiftRightBytesInVector(Vector128<byte> value, [ConstantExpected(Max = (byte)15)] byte numBytes) |
There was a problem hiding this comment.
There's something not right in one of the methods below on Arm64.
@tannergooding @saucecontrol Would either of you be able to do a quick readthrough and set me right?
There was a problem hiding this comment.
Figured it out. It was left shift. I'd forgotten to offset.
| /// Calculates <paramref name="x"/> % 4 | ||
| /// </summary> | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public static nuint Modulo4(nuint x) => x & 3; |
There was a problem hiding this comment.
Just noting that x % 4 should already get optimized to x & 3 by the JIT since x is nuint (and therefore definitely unsigned)
There was a problem hiding this comment.
Thanks yeah, I just kept it the same for consistency.
| ref Vector512<float> vs0 = ref Unsafe.Add(ref sourceBase, i); | ||
| ref Vector512<float> vd0 = ref Unsafe.Add(ref destinationBase, i); | ||
|
|
||
| vd0 = Avx.Permute(vs0, control); | ||
| Unsafe.Add(ref vd0, 1) = Avx.Permute(Unsafe.Add(ref vs0, 1), control); | ||
| Unsafe.Add(ref vd0, 2) = Avx.Permute(Unsafe.Add(ref vs0, 2), control); | ||
| Unsafe.Add(ref vd0, 3) = Avx.Permute(Unsafe.Add(ref vs0, 3), control); | ||
| vd0 = Vector512Utilities.Shuffle(vs0, control); | ||
| Unsafe.Add(ref vd0, (nuint)1) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)1), control); | ||
| Unsafe.Add(ref vd0, (nuint)2) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)2), control); | ||
| Unsafe.Add(ref vd0, (nuint)3) = Vector512Utilities.Shuffle(Unsafe.Add(ref vs0, (nuint)3), control); |
There was a problem hiding this comment.
Worth noting that you could do this like the following:
Vector512Utilities.Shuffle(Vector512.LoadUnsafe(ref sourceBase, i + 0), control).StoreUnsafe(ref destinationBase, i + 0).
Vector512Utilities.Shuffle(Vector512.LoadUnsafe(ref sourceBase, i + 1), control).StoreUnsafe(ref destinationBase, i + 1).
Vector512Utilities.Shuffle(Vector512.LoadUnsafe(ref sourceBase, i + 2), control).StoreUnsafe(ref destinationBase, i + 2).
Vector512Utilities.Shuffle(Vector512.LoadUnsafe(ref sourceBase, i + 3), control).StoreUnsafe(ref destinationBase, i + 3).It shouldn't result in any codegen differences, but avoids needing to manipulate the byref and uses direct hardware intrinsic APIs, rather than the Unsafe helpers, so can be easier to read/understand at least IMO.
There was a problem hiding this comment.
sourceBase is Vector512<float> so Vector512.LoadUnsafe(ref sourceBase, i + 0) would yield Vector512<Vector512<float>>. I could use float as the base ref type but that complicates the offsetting which confuses me and causes me to make mistakes.
tannergooding
left a comment
There was a problem hiding this comment.
LGTM, just left a couple comments on newer APIs that might help with readability
| /// </summary> | ||
| /// <returns>The <see cref="PixelTypeInfo"/>.</returns> | ||
| #pragma warning disable CA1000 | ||
| static abstract PixelTypeInfo GetPixelTypeInfo(); |
There was a problem hiding this comment.
Just curious. Is there a specific reason to kick it from the interface and only have it in the implementations? Probably it was never called from the interface and only from specific implementations?
There was a problem hiding this comment.
Actually, this is just temporary. I had to hack to get the solution to build because we were misusing ApproximateFloatComparer in the tests.
| <Include Path="..\shared-infrastructure\sixlabors.ruleset" Action="Default" /> | ||
| <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> | ||
| <Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features"> | ||
| <Rule Id="IDE0290" Action="None" /> |
There was a problem hiding this comment.
This should also be suppressible via .editorconfig using csharp_style_prefer_primary_constructors = false:none (or a different severity level if you want to block use of primary constructors altogether, such as silent, suggestion, warning, or error)
There was a problem hiding this comment.
Thanks. Yeah, I’ll do that upstream. Not sold on primary constructors. The syntax doesn’t sit right with me.
Prerequisites
Description
Fixes #2232 and #594
Optimizes and modernizes SIMD Vector4 packing operations.I'm leaving this for a follow up PRI don't expect anyone to reasonably find the time to analyze this line-by-line as it's a massive piece of work. However, changes on the whole are simplistic and the developer benefit massive.
API change Elevator Pitch
The abomination that is.
Becomes, as nature intended.
All other conversion methods follow suit where applicable.